﻿#pragma once
#include "XyNet/Global.h"

// 单件使用说明：
// 1、需要时自动加载。使用getInstance()，依据创建策略生成单件（可以生成子类）。
// 2、手动加载。在第一次getInstance()前调用new Singleton（可以是子类），或者是定义策略，再调用create()
// 3、如果单件是带参构造函数，需要使用NullSingletonCreatePolicy，并手动create单件或使用自定义策略

namespace XyNet
{
	/// 单件创建策略
	template <typename T>
	class SingletonCreatePolicy : noncopyable
	{
	public:
		virtual T* create() = 0;
	};

	/// 空单件创建策略
	template <typename T>
	class NullSingletonCreatePolicy : public SingletonCreatePolicy < T >
	{
	public:
		virtual T* create() override
		{
			return nullptr;
		}
	};

	/// 基类单件创建策略
	template <typename T>
	class BaseSingletonCreatePolicy : public SingletonCreatePolicy < T >
	{
	public:
		virtual T* create() override
		{
			return new T;
		}
	};

	/// 派生类单件创建策略
	template <typename T, typename DerivedT>
	class DerivedSingletonCreatePolicy : public SingletonCreatePolicy < T >
	{
	public:
		virtual T* create() override
		{
			return new DerivedT;
		}
	};

	//////////////////////////////////////////////////////////////////////////////////////

	/// 单件实现，用于确保析构时正确表示销毁状态
	template <typename T>
	class SingletonImplement : noncopyable
	{
	public:
		SingletonImplement(shared_ptr<SingletonCreatePolicy<T>> createPolicy)
			: _createPolicy(createPolicy), _destroyed(false)
		{
		}

		~SingletonImplement()
		{
			destroy();
		}

		/// 设置单件创建策略
		inline void setCreatePolicy(SingletonCreatePolicy<T>* createPolicy)
		{
			_createPolicy.reset(createPolicy);
		}

		/// 使用策略创建单件
		inline T* createByPolicy()
		{
			return _createPolicy->create();
		}

		/// 获取单件，如果没有创建，按策略创建
		inline T* getInstance()
		{
			if (!_instance)
			{
				unique_lock<mutex> lock(_mutex);
				if (!_instance)
					createByPolicy();
			}
			assert((bool)_instance && "单件创建失败");	// 有可能创建失败或什么都没创建
			return _instance.get();
		}

		/// 设置单件
		inline void setInstance(T* instance)
		{
			assert(!_instance && "单件已经创建");
			_instance.reset(instance);
			_destroyed = false;
		}

		/// 单件是否被销毁
		inline bool isDestroyed()
		{
			return _destroyed;
		}

		/// 销毁单件
		inline void destroy()
		{
			// 由于在单件销毁过程中可能发生隐式依赖，
			// 所以要先标记_destroyed为true，再销毁单件
			//CHECK(_instance);
			_destroyed = true;
			_instance.reset();
		}

	private:
		/// 单件实例
		unique_ptr<T> _instance;
		/// 创建策略
		shared_ptr<SingletonCreatePolicy<T>> _createPolicy;
		/// 创建锁
		mutex _mutex;
		/// 是否被销毁
		bool _destroyed;
	};

	//////////////////////////////////////////////////////////////////////////

	/// 单件类，使用虚继承可以防止被派生
	template <typename T>
	class Singleton : noncopyable
	{
	public:
		Singleton()
		{
			_implement.setInstance(static_cast<T*>(this));
		}

		~Singleton()
		{
			// 在这里标记_destroyed起不到实际的效果，所以移动至Wrapper类中
			//_destroyed = true;
		}

		/// 设置单件创建策略
		inline static void setCreatePolicy(SingletonCreatePolicy<T>* createPolicy)
		{
			_implement.setCreatePolicy(createPolicy);
		}

		/// 使用策略创建单件
		inline static T* createByPolicy()
		{
			return _implement.createByPolicy();
		}

#if !defined(XYNET_COMPILER_MSVC) || _MSC_VER >= 1800
		/// 手动创建单件
		template <typename Type, typename... Args>
		inline static T* create(const Args&... args)
		{
			return new Type(args...);
		}
#else
		/// 手动创建单件
		template <typename Type>
		inline static T* create()
		{
			return new Type;
		}

		/// 手动创建单件
		template <typename Type, typename T1>
		inline static T* create(const T1& a1)
		{
			return new Type(a1);
		}

		/// 手动创建单件
		template <typename Type, typename T1, typename T2>
		inline static T* create(const T1& a1, const T2& a2)
		{
			return new Type(a1, a2);
		}

		/// 手动创建单件
		template <typename Type, typename T1, typename T2, typename T3>
		inline static T* create(const T1& a1, const T2& a2, const T3& a3)
		{
			return new Type(a1, a2, a3);
		}

		/// 手动创建单件
		template <typename Type, typename T1, typename T2, typename T3, typename T4>
		inline static T* create(const T1& a1, const T2& a2, const T3& a3, const T4& a4)
		{
			return new Type(a1, a2, a3, a4);
		}

		/// 手动创建单件
		template <typename Type, typename T1, typename T2, typename T3, typename T4, typename T5>
		inline static T* create(const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5)
		{
			return new Type(a1, a2, a3, a4, a5);
		}
#endif

		/// 获取单件
		inline static T* getInstance()
		{
			return _implement.getInstance();
		}

		/// 单件是否被销毁
		inline static bool isDestroyed()
		{
			return _implement.isDestroyed();
		}

		/// 销毁单件
		inline static void destroy()
		{
			_implement.destroy();
		}

	private:
		static SingletonImplement<T> _implement;

		// 以下宏不能定义在命名空间中
#define XYNET_IMPLEMENT_NULL_SINGLETON(base) \
	template<> XyNet::SingletonImplement<base> \
	XyNet::Singleton<base>::_implement(make_shared<XyNet::NullSingletonCreatePolicy<base>>());

#define XYNET_IMPLEMENT_BASE_SINGLETON(base) \
	template<> XyNet::SingletonImplement<base> \
	XyNet::Singleton<base>::_implement(make_shared<XyNet::BaseSingletonCreatePolicy<base>>());

#define XYNET_IMPLEMENT_DERIVED_SINGLETON(base, derived) \
	template<> XyNet::SingletonImplement<base> \
	XyNet::Singleton<base>::_implement(make_shared<XyNet::DerivedSingletonCreatePolicy<base, derived>>());
	};

	//////////////////////////////////////////////////////////////////////////

	/// 带有默认对象的类
	template <typename T>
	class DefaultObject : noncopyable
	{
	public:
		inline static T* getDefault()
		{
			if (!_default)
			{
				static mutex _mutex;
				unique_lock<mutex> lock(_mutex);
				if (!_default)
					_default.reset(new T);
			}
			assert((bool)_default && "默认对象创建失败");	// 有可能创建失败或什么都没创建
			return _default.get();
		}

	private:
		/// 默认对象
		static unique_ptr<T> _default;

#define XYNET_IMPLEMENT_DEFAULT_OBJECT(type) \
	template<> unique_ptr<type> XyNet::DefaultObject<type>::_default(nullptr);
	};
}